#include "../lib_include/Logger.h"
#include "../lib_include/Channel.h"
#include "../lib_include/EventLoop.h"

#include <sstream>
#include <poll.h>

using namespace netlib;
using namespace netlib::net;

const int Channel::kNoneEvent = 0;                      // 空事件
const int Channel::kReadEvent = POLLIN | POLLPRI;       // 可读事件
const int Channel::kWriteEvent = POLLOUT;               // 可写事件

Channel::Channel(EventLoop* loop, int fd__)
  : loop_(loop),
    fd_(fd__),
    events_(0),
    revents_(0),
    index_(-1),
    logHup_(true),
    tied_(false),
    eventHandling_(false),
    addedToLoop_(false)
{ }

Channel::~Channel()
{
    assert(!eventHandling_);
    assert(!addedToLoop_);
    if (loop_->isInLoopThread())
        assert(!loop_->hasChannel(this));
}

// 保存TCP连接的副本指针并设置标识，用于安全关闭连接
void Channel::tie(const std::shared_ptr<void>& obj)
{
    tie_ = obj;
    tied_ = true;
}

void Channel::update() // 事件表更新
{
    addedToLoop_ = true;
    loop_->updateChannel(this);
}

void Channel::remove() // 从事件表中移除该通道
{
    assert(isNoneEvent());
    addedToLoop_ = false;
    loop_->removeChannel(this);
}

void Channel::handleEvent(Timestamp receiveTime) // 事件处理回调函数
{
    std::shared_ptr<void> guard;
    if (tied_) // 成功建立连接后，设置weak_ptr副本和tied_标志
    {
        guard = tie_.lock(); // 这里提升计数加一,防止shared_ptr的连接提前析构而崩溃
        if (guard)
            handleEventWithGuard(receiveTime);
    }
    else
        handleEventWithGuard(receiveTime);
}

void Channel::handleEventWithGuard(Timestamp receiveTime) // 事件处理回调函数
{
    eventHandling_ = true; // 设置状态为正在处理事件
    LOG_TRACE << reventsToString(); // 记录到日志

    if ((revents_ & POLLHUP) && !(revents_ & POLLIN)) // POLLHUP对端关闭了连接
    {
        if (logHup_)
            LOG_WARN << "fd = " << fd_ << " Channel::handle_event() POLLHUP";
        if (closeCallback_)
            closeCallback_();
    }

    if (revents_ & POLLNVAL) // 描述符未打开或者非法
        LOG_WARN << "fd = " << fd_ << " Channel::handle_event() POLLNVAL";

    if (revents_ & (POLLERR | POLLNVAL)) // 错误事件
        if (errorCallback_)
            errorCallback_();

    if (revents_ & (POLLIN | POLLPRI | POLLRDHUP)) // 可读事件
        if (readCallback_)
            readCallback_(receiveTime);

    if (revents_ & POLLOUT) // 可写事件
        if (writeCallback_)
            writeCallback_();

    eventHandling_ = false; // 设置状态为不在处理事件
}

string Channel::reventsToString() const // 作为调试用途，将发生的事件转化成string返回
{
    return eventsToString(fd_, revents_);
}

string Channel::eventsToString() const // 作为调试用途，将注册的事件转化成string返回
{
    return eventsToString(fd_, events_);
}

string Channel::eventsToString(int fd, int ev) // 将事件转换成string返回
{
    std::ostringstream oss;
    oss << fd << ": ";
    if (ev & POLLIN)
        oss << "IN ";
    if (ev & POLLPRI)
        oss << "PRI ";
    if (ev & POLLOUT)
        oss << "OUT ";
    if (ev & POLLHUP)
        oss << "HUP ";
    if (ev & POLLRDHUP)
        oss << "RDHUP ";
    if (ev & POLLERR)
        oss << "ERR ";
    if (ev & POLLNVAL)
        oss << "NVAL ";

    return oss.str();
}
